#include "memchunkdialog.h"
#include "tools.h"
#include "ui_memchunkdialog.h"

MemChunkDialog::MemChunkDialog( const QByteArray &d, u32 addr, u32 viewMode, QWidget *parent ) :
    QDialog(parent),
    ui(new Ui::MemChunkDialog)
{
    ui->setupUi( this );
    setWindowTitle( tr( "Ram View - 0x%1 bytes starting at 0x%2" )
                    .arg( (quint32)d.size(), 2, 16, QChar( '0' ) )
                    .arg( addr, 8, 16, QChar( '0' ) ) );

    ui->plainTextEdit->appendPlainText( MakeHexDump( d, addr, viewMode ) );
}

MemChunkDialog::~MemChunkDialog()
{
    delete ui;
}

QByteArray MemChunkDialog::MakeHexDump( const QByteArray &d,
                                   u32 addr,
                                   u32 viewMode )
{
    // make a pretty hex string
    bool doAscii = ( viewMode & V_Ascii );
    bool doOffset = ( viewMode & V_AbsoluteOffset ) || ( viewMode & V_RelativeOfset );
    u32 charsPerLine = 6 + ( 8 * 4 ) + 3;   // line ending, 4 columns of hex, and 3 spaces
    if( doAscii )
    {
        charsPerLine += 17;                 // 16 characters and a space
    }
    if( doOffset )
    {
        charsPerLine += 8 + 2;             // 8 characters and 2 spaces
    }
    u32 lines = RU( d.size(), 0x10 ) / 0x10;
    u32 bufSize = lines * charsPerLine;
    u32 pOff = ( viewMode & V_AbsoluteOffset ) ? addr : 0;

    QByteArray hba( bufSize, Qt::Uninitialized );
    u32 bOffset = 0;
    char *bp = (char*)hba.constData();

    u8 *data = (u8*)d.constData();
    u32 len = d.size();
    for( u32 off = 0; off < len; off += 16, pOff += 16 )
    {
        if( doOffset )
        {
            bOffset += sprintf( &bp[ bOffset ], "%08x  ", pOff );
        }
        for( u32 i = 0; i < 16; i++ )
        {
            if( ( i + 1 ) % 4 )
            {
                if ( ( i + off ) >= len )
                {
                    bOffset += sprintf( &bp[ bOffset ], "  " );
                }
                else
                {
                    bOffset += sprintf( &bp[ bOffset ], "%02x", data[ off + i ] );
                }
            }
            else
            {
                if ( ( i + off ) >= len )
                {
                    bOffset += sprintf( &bp[ bOffset ], "   " );
                }
                else
                {
                    bOffset += sprintf( &bp[ bOffset ], "%02x ", data[ off + i ] );
                }
            }
        }
        if( doAscii )
        {
            bp[ bOffset++ ] = ' ';
            for( u32 i = 0; i < 16; i++ )
            {
                if ( ( i + off ) >= len )
                {
                    bp[ bOffset++ ] = ' ';
                }
                else
                {
                    bp[ bOffset++ ] = ascii( data[ off + i ] );
                }
            }
        }

        bp[ bOffset++ ] = '\n';
    }
    bp[ bOffset++ ] = 0;

    return hba;
}

void MemChunkDialog::on_pushButton_clicked()
{
    QDialog::accept();
}

void MemChunkDialog::ShowArray( const QByteArray &d, u32 addr, u32 viewMode, QWidget *parent )
{
    MemChunkDialog dlg( d, addr, viewMode, parent );
    dlg.exec();
}
